package com.example.springboot_selenium_demo.util;

import com.google.common.collect.ImmutableMap;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.UnsupportedCommandException;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.remote.*;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;

import java.net.URL;
import java.util.Hashtable;

public class ActiveRemoteWebDriverSession {
	
	private URL addressOfRemoteServer;
	private final HttpClient client;
	private final HttpClient.Factory httpClientFactory;
	
	private CommandCodec<HttpRequest> commandCodec;
	private ResponseCodec<HttpResponse> responseCodec;

	public ActiveRemoteWebDriverSession(URL addressOfRemoteServer, Capabilities capabilities) {
		this.addressOfRemoteServer=addressOfRemoteServer;
		this.httpClientFactory = HttpClient.Factory.createDefault();
		this.client = httpClientFactory.createClient(addressOfRemoteServer);
		commandCodec = Dialect.W3C.getCommandCodec();
		responseCodec = Dialect.W3C.getResponseCodec();
	}

	public Hashtable<String, ActiveHttpCommandSession> getSessionIds() {
		Hashtable<String, ActiveHttpCommandSession>  list = new Hashtable<String, ActiveHttpCommandSession>();
		try {
			HttpRequest httpRequest = commandCodec.encode(new Command(null, DriverCommand.GET_ALL_SESSIONS));
			try {
				HttpResponse httpResponse = client.execute(httpRequest);
				Response response = responseCodec.decode(httpResponse);

				if (response != null) {
					System.err.println(response.getValue()); 
					JSONArray jsonArray = JSONArray.fromObject(response.getValue());
					for (int i = 0; i < jsonArray.size(); i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						
						String opaqueKey= jsonObject.getString("id");
						
						SessionId sessionId=new SessionId(opaqueKey);
						ActiveHttpCommandExecutor activeHttpCommandExecutor=new ActiveHttpCommandExecutor(sessionId, addressOfRemoteServer);
						
						ActiveHttpCommandSession activeHttpCommandSession=new ActiveHttpCommandSession(sessionId, activeHttpCommandExecutor);
						list.put(opaqueKey, activeHttpCommandSession);
					}
					
				}
			} catch (UnsupportedCommandException e) {
				throw e;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}
	
	public void clearDeathSession() {
		try {
			HttpRequest httpRequest = commandCodec.encode(new Command(null, DriverCommand.GET_ALL_SESSIONS));
			try {
				HttpResponse httpResponse = client.execute(httpRequest);
				Response response = responseCodec.decode(httpResponse);

				if (response != null) {
					JSONArray jsonArray = JSONArray.fromObject(response.getValue());
					for (int i = 0; i < jsonArray.size(); i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						String opaqueKey= jsonObject.getString("id");
						SessionId sessionId=new SessionId(opaqueKey);
						ActiveHttpCommandExecutor activeHttpCommandExecutor=new ActiveHttpCommandExecutor(sessionId, addressOfRemoteServer);
						new RemoteWebDriver(activeHttpCommandExecutor, DesiredCapabilities.firefox());
						Command command=new Command(sessionId, DriverCommand.GET_CURRENT_URL);
						response = activeHttpCommandExecutor.execute(command);
						if (response==null || response.getValue() instanceof WebDriverException) {
							command = new Command(sessionId, DriverCommand.QUIT, ImmutableMap.of());
							response = activeHttpCommandExecutor.execute(command);
						}
					}
					
				}
			} catch (UnsupportedCommandException e) {
				throw e;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
